﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Web;
using Proggy.Web.Cms.Cache;
using System.Text.RegularExpressions;

namespace Proggy.Web.Cms.Core.Models
{
    /// <summary>
    /// Url added using content selector
    /// </summary>
    public class AddedUrl
    {
        /// <summary>
        /// Url type
        /// </summary>
        public AddedUrlType UrlType { get; set; }

        /// <summary>
        /// Optional - link name
        /// </summary>
        public string Text { get; set; }

        /// <summary>
        /// Optional - link description
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Link title
        /// </summary>
        public string LinkTitle { get; set; }

        /// <summary>
        /// Optional - mailto subject
        /// </summary>
        public string MailToSubject { get; set; }

        /// <summary>
        /// NodeId if internal 
        /// </summary>
        public int? NodeId { get; set; }

        /// <summary>
        /// Link if external
        /// </summary>
        public string ExternalUrl { get; set; }

        /// <summary>
        /// Mail to email address if mailto
        /// </summary>
        public string MailToAddress { get; set; }

        /// <summary>
        /// Get href component for this added url
        /// </summary>
        /// <returns></returns>
        public string GetHrefComponent()
        {
            // switch url type
            switch (this.UrlType)
            {
                case AddedUrlType.MailTo:
                    {
                        // get subject
                        var subject =
                            string.IsNullOrEmpty(this.MailToSubject) ?
                            "" :
                            "?subject=" + HttpUtility.UrlEncode(this.MailToSubject);

                        //
                        return "mailto:" + this.MailToAddress + subject;
                    }
                case AddedUrlType.External:
                    {
                        //
                        return this.ExternalUrl;
                    }
                case AddedUrlType.Internal:
                    {
                        return AddedUrl.GetProggyLinkFromNodeId((int)this.NodeId);
                    }
            }

            //
            return null;
        }

        /// <summary>
        /// Returns a link in proggy link format
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public static string GetProggyLinkFromNodeId(int nodeId)
        {
            return ProggyLinkPrefix + nodeId;
        }

        /// <summary>
        /// Returns true if href matches proggy link format
        /// </summary>
        /// <param name="href"></param>
        /// <returns></returns>
        public static bool IsProggyLink(string href)
        {
            // get match
            var match = Regex.IsMatch(href, AddedUrl.ProggyLinkMatchPattern);

            //
            return match;
        }

        /// <summary>
        /// Returns node id from proggy link
        /// </summary>
        /// <param name="href"></param>
        /// <returns></returns>
        public static int? GetNodeIdFromProggyLink(string href)
        {
            var match = Regex.Match(href, ProggyLinkMatchPattern);

            return Convert.ToInt32(match.Groups[1].Value);
        }

        /// <summary>
        /// Returns true if href matches mailto link
        /// </summary>
        /// <param name="href"></param>
        /// <returns></returns>
        public static bool IsMailtoLink(string href)
        {
            try
            {
                return Regex.IsMatch(href, MailToMatchPattern, RegexOptions.IgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Gets mailto address from mailto link
        /// </summary>
        /// <param name="href"></param>
        /// <returns></returns>
        public static string GetMailToAddress(string href)
        {
            //
            string output = "";

            try
            {
                output = Regex.Match(href, MailToFullPattern).Groups[1].Value;

                if (string.IsNullOrEmpty(output))
                {
                    try
                    {
                        output = Regex.Match(href, MailToNoSubjectPattern).Groups[1].Value;
                    }
                    catch
                    {
                        output = "";
                    }
                }
            }
            catch
            {
                try
                {
                    output = Regex.Match(href, MailToNoSubjectPattern).Groups[1].Value;
                }
                catch
                {
                    output = "";
                }
            }

            return output;
        }

        /// <summary>
        /// Gets mailto subject from mailto link
        /// </summary>
        /// <param name="href"></param>
        /// <returns></returns>
        public static string GetMailToSubject(string href)
        {
            try
            {
                return Regex.Match(href, MailToFullPattern).Groups[3].Value;
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// [PROGGYLINK|
        /// </summary>
        public const string ProggyLinkPrefix = "PROGGYLINK_____";

        /// <summary>
        /// Regex match for proggy urls
        /// </summary>
        public const string ProggyLinkMatchPattern = ProggyLinkPrefix + @"([0-9]+)";

        /// <summary>
        /// Regex match for mailto
        /// </summary>
        public const string MailToMatchPattern = @"\bmailto:\b.*$";

        /// <summary>
        /// Regex match for mailtos
        /// </summary>
        public const string MailToFullPattern = @"mailto:(\b.*)(\?subject\=)(.*)";

        /// <summary>
        /// Regex match for mailtos no subject
        /// </summary>
        public const string MailToNoSubjectPattern = @"mailto:(\b.*)";

        /// <summary>
        /// Converts html with proggy links to node ids (as long us URL cache is present)
        /// </summary>
        /// <param name="unencodedHtmlString"></param>
        /// <returns></returns>
        public static string ConvertHtmlWithProggyLinks(string unencodedHtmlString)
        {
            //
            var result =
                Regex.Replace(
                    unencodedHtmlString,
                    ProggyLinkMatchPattern,
                    match => { 
                        
                        // get url
                        var url = UrlCache.GetUrlFromNodeId(Convert.ToInt32(match.Groups[1].Value));

                        //
                        return url;

                    });

            // 
            return result;

            //// get matches
            //var matches = Regex.Matches(htmlString, ProggyLinkMatchPattern);

            //// iterate
            //foreach (Match match in matches)
            //{
            //    // get url
            //    var url = UrlCache.GetUrlFromNodeId(Convert.ToInt32(match.Groups[1].Value));

            //    // replace
            //    match.
            //}

            ////
            //return htmlString;
        }        
    }
}
